package com.sciology.xpathutility;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.internal.util.BundleUtility;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

import com.sciology.xpathutility.contentassist.CompletionProposalXMLHandler;
import com.sciology.xpathutility.utils.XPathUtilLog;

/**
 * The activator class controls the plug-in life cycle
 */
public class XPathWorkbookActivator
        extends AbstractUIPlugin {

    // The plug-in ID
    public static final String PLUGIN_ID = "com.sciology.xpathutility";

    /**
     * The name of the dialog settings file (value 
     * <code>"dialog_settings.xml"</code>).
     */
    private static final String FN_DIALOG_SETTINGS = "dialog_settings.xml"; //$NON-NLS-1$
    private static final String PROPOSAL_FILE_NAME = "xalanCompletion.xml"; //$NON-NLS-1$

    // The shared instance
    private static XPathWorkbookActivator plugin;

    /**
     * Storage for dialog and wizard data; <code>null</code> if not yet
     * initialized.
     */
    private DialogSettings dialogSettings = null;

    public XPathWorkbookActivator() {
        plugin = this;
    }

    public void start(BundleContext context) throws Exception {
        super.start(context);
    }

    public void stop(BundleContext context) throws Exception {
        plugin = null;
        super.stop(context);
    }

    public static XPathWorkbookActivator getDefault() {
        return plugin;
    }

    protected void initializeDefaultPreferences(IPreferenceStore store) {
        super.initializeDefaultPreferences(store);
    }

    /**
     * Loads the dialog settings for this plug-in.
     * The default implementation first looks for a standard named file in the 
     * plug-in's read/write state area; if no such file exists, the plug-in's
     * install directory is checked to see if one was installed with some default
     * settings; if no file is found in either place, a new empty dialog settings
     * is created. If a problem occurs, an empty settings is silently used.
     * <p>
     * This framework method may be overridden, although this is typically
     * unnecessary.
     * </p>
     */
    protected void loadDialogSettings() {
        dialogSettings = new DialogSettings("Workbench"); //$NON-NLS-1$
        IPath dataLocation = getStateLocationOrNull();
        if (dataLocation != null) {
            // try r/w state area in the local file system
            String readWritePath = dataLocation.append(FN_DIALOG_SETTINGS).toOSString();
            File settingsFile = new File(readWritePath);
            if (settingsFile.exists()) {
                try {
                    dialogSettings.load(readWritePath);
                } catch (IOException e) {
                    // load failed so ensure we have an empty settings
                    dialogSettings = new DialogSettings("Workbench"); //$NON-NLS-1$
                }
                return;
            }
        }
        // otherwise look for bundle specific dialog settings
        URL dsURL = BundleUtility.find(getBundle(), FN_DIALOG_SETTINGS);
        if (dsURL == null) {
            return;
        }
        InputStream is = null;
        try {
            is = dsURL.openStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8")); //$NON-NLS-1$
            dialogSettings.load(reader);
        } catch (IOException e) {
            // load failed so ensure we have an empty settings
            dialogSettings = new DialogSettings("Workbench"); //$NON-NLS-1$
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                // do nothing
            }
        }
    }

    /**
     * Returns the dialog settings for this UI plug-in.
     * The dialog settings is used to hold persistent state data for the various
     * wizards and dialogs of this plug-in in the context of a workbench. 
     * <p>If an error occurs reading the dialog store, an empty one is quietly created
     * and returned.</p>
     * <p>Subclasses may override this method but are not expected to.</p>
     * @return the dialog settings
     */
    public IDialogSettings getDialogSettings() {
        if (dialogSettings == null) {
            loadDialogSettings();
        }
        return dialogSettings;
    }

    /**
     * FOR INTERNAL WORKBENCH USE ONLY. 
     * 
     * Returns the path to a location in the file system that can be used 
     * to persist/restore state between workbench invocations.
     * If the location did not exist prior to this call it will  be created.
     * Returns <code>null</code> if no such location is available.
     * 
     * @return path to a location in the file system where this plug-in can
     * persist data between sessions, or <code>null</code> if no such
     * location is available.
     * @since 3.1
     */
    private IPath getStateLocationOrNull() {
        try {
            return getStateLocation();
        } catch (IllegalStateException e) {
            // This occurs if -data=@none is explicitly specified, so ignore this silently.
            // Is this OK? See bug 85071.
            return null;
        }
    }

    /**
     * Reads in the TAB-Completion-proposals file and creates the proposal-structures in the passed Collections/Maps.
     * 
     * @param p_proposals
     *          a HashMap to be filled with the proposals
     * @param p_keys
     *          an ArrayList to be filled with the keys
     */
    public void initCompletionsFromFile(HashMap p_proposals, ArrayList p_keys) {
        try {
            InputStream propFileStream = openStream(new Path(PROPOSAL_FILE_NAME), true);
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            parser.parse(propFileStream, new CompletionProposalXMLHandler(p_proposals, p_keys));
        } catch (Exception ex) {
            XPathUtilLog.logError(getDefault(), ex.toString());
        }
    }

}
